package com.miaowang.salad.net;

import java.io.File;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.NameValuePair;
import org.json.JSONException;
import org.json.JSONStringer;

import android.util.Log;

import com.miaowang.salad.Common;
import com.miaowang.salad.util.PrefUtils;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.OkUrlFactory;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

public class OkHttpUtils {

	// 请求数据类型
	public static final MediaType MEDIA_TYPE_JSON = MediaType
			.parse("application/json; charset=utf-8");
	public static final MediaType MEDIA_TYPE_FORM = MediaType
			.parse("multipart/form-data; charset=utf-8");

	private static final OkHttpClient mOkHttpClient = new OkHttpClient();

	public static void setHttpsClient(OkHttpClient client) {
		if (client == null) {
			throw new NullPointerException("Client must not be null.");
		} else {
			try {
				TrustManager tm = new X509TrustManager() {
					public void checkClientTrusted(X509Certificate[] chain,
							String authType) throws CertificateException {
					}

					public void checkServerTrusted(X509Certificate[] chain,
							String authType) throws CertificateException {
					}

					public X509Certificate[] getAcceptedIssuers() {
						return null;
					}
				};

				SSLContext e = SSLContext.getInstance("TLS");

				e.init(null, new TrustManager[] { tm }, null);

				client.setSslSocketFactory(e.getSocketFactory());

			} catch (Exception e) {
				throw new AssertionError();
			}

		}
	}

	static {
//		setHttpsClient(mOkHttpClient);
		mOkHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
		mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
		mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
	}

	/**
	 * 同步请求 不会开启异步线程。
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 */
	public static Response execute(Request request) throws IOException {
		return mOkHttpClient.newCall(request).execute();
	}

	/**
	 * 异步请求
	 * 
	 * @param request
	 * @param responeseCallBack
	 */
	public static void execute(Request request, Callback responeseCallBack) {
		mOkHttpClient.newCall(request).enqueue(responeseCallBack);
	}

	/**
	 * get 请求
	 * 
	 * @param url
	 * @return
	 * @throws IOException
	 */
	public static String get(String url) throws IOException {
		Request request = new Request.Builder()
				.header("Authorization",
						PrefUtils.getString(Common.gobleContext,
								Common.PREF_TOKEN, ""))
				.addHeader("Accept", "*/*").url(url).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/**
	 * post 提交String
	 * 
	 * @param url
	 * @return
	 * @throws IOException
	 */
	public static String post(String url) throws IOException {
		RequestBody formBody = new FormEncodingBuilder().add("default", "0")
				.build();
		Request request = new Request.Builder().url(url).post(formBody).build();

		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/**
	 * post 提交String/Json
	 * 
	 * @param url
	 * @param json
	 * @return
	 * @throws IOException
	 */
	public static String post(String url, String json) throws IOException {
		RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
		Request request = new Request.Builder()
				.header("Authorization",
						PrefUtils.getString(Common.gobleContext,
								Common.PREF_TOKEN, ""))
				.addHeader("Accept", "*/*").url(url).post(body).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/**
	 * 此方法添加一个token 和 headrer accept
	 * 
	 * @param url
	 * @param json
	 * @return
	 * @throws IOException
	 */
	public static String postWithToken(String url, String json)
			throws IOException {
		RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
		Request request = new Request.Builder()
				.header("Authorization",
						PrefUtils.getString(Common.gobleContext,
								Common.PREF_TOKEN, ""))
				.addHeader("Accept", "*/*").url(url).post(body).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/**
	 * post 提交键值对
	 *
	 * @param url
	 * @param key
	 * @param value
	 * @return
	 * @throws IOException
	 */
	public static String post(String url, String key, String value)
			throws IOException {
		RequestBody formBody = new FormEncodingBuilder().add(key, value)
				.build();
		Request request = new Request.Builder()
				.header("Authorization",
						PrefUtils.getString(Common.gobleContext,
								Common.PREF_TOKEN, ""))
				.addHeader("Accept", "*/*").url(url).post(formBody).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	public static String post(String url, String key, String value,
			String key1, String value1) throws IOException {
		RequestBody formBody = new FormEncodingBuilder().add(key, value)
				.add(key1, value1).build();
		Request request = new Request.Builder().addHeader("Accept", "*/*")
				.url(url).post(formBody).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/**
	 * @param url
	 * @param key
	 * @param value
	 * @return
	 * @throws IOException
	 */
	public static String post(String url, String key[], String value[])
			throws IOException {
		FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder();
		for (int i = 0; i < key.length; i++) {
			formEncodingBuilder.add(key[i], value[i]);
		}
		RequestBody formBody = formEncodingBuilder.build();

		Request request = new Request.Builder().addHeader("Accept", "*/*")
				.url(url).post(formBody).build();
		Response response = mOkHttpClient.newCall(request).execute();
		Log.v("headers", response.headers().toString());
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}

	/**
	 * 文件上传 如果错误是否是header accept
	 * 
	 * @param url
	 * @param file
	 * @return
	 * @throws Exception
	 */
	public static boolean post(String url, File file) throws Exception {
		Request request = new Request.Builder().url(url)
				.post(RequestBody.create(MEDIA_TYPE_JSON, file)).build();
		Response response = mOkHttpClient.newCall(request).execute();
		if (response.isSuccessful()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 生成Json形式参数
	 * 
	 * @param nameValuePairs
	 * @return
	 */
	private String generateRequest(NameValuePair... nameValuePairs) {
		List<NameValuePair> params = stripNulls(nameValuePairs);
		JSONStringer jStringer = new JSONStringer();
		try {
			jStringer.object();
			for (NameValuePair param : params) {
				if (param.getValue() != null) {
					jStringer.key(param.getName()).value(param.getValue());
				}
			}
			jStringer.endObject();
		} catch (JSONException e) {
			return null;
		}
		return jStringer.toString();
	}

	private List<NameValuePair> stripNulls(NameValuePair... nameValuePairs) {
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		for (int i = 0; i < nameValuePairs.length; i++) {
			NameValuePair param = nameValuePairs[i];
			if (param.getValue() != null) {
				params.add(param);
			}
		}
		return params;
	}

}
